package com.cloud.common.utils;

import java.util.Objects;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 利用java8的function实现一个重试工具类
 *
 * @author 王霄
 * @date 2021/4/30
 */
public class RetryUtil {

    /**
     * @param supplier     业务方法，返回结果T，内部异常需要业务逻辑自行捕获，通用方法不做处理。
     * @param predicate    对结果进行断言，true结束重试，false继续执行
     * @param consumer     对结果进行一次消费
     * @param retryCount   重试次数（初次执行不包含在计数范围内）
     * @param defaultValue 达到最大重试次数，要返回的默认值
     * @param <T>          业务逻辑结果类型
     * @return 业务逻辑结果
     */
    public static <T> T retry(Supplier<T> supplier, Predicate<T> predicate, Consumer<T> consumer, int retryCount, T defaultValue) {
        Objects.requireNonNull(supplier);
        Objects.requireNonNull(predicate);
        for (int i = 0; i <= retryCount; i++) {
            T result = supplier.get();
            if (consumer != null) {
                consumer.accept(result);
            }
            if (predicate.test(result)) {
                return result;
            }
        }
        return defaultValue;
    }

    public static <T> T retry(Supplier<T> supplier, Predicate<T> predicate, int retryCount) {
        return retry(supplier, predicate, null, retryCount, null);
    }

    public static <T> T retry(Supplier<T> supplier, Predicate<T> predicate, int retryCount, T defaultValue) {
        return retry(supplier, predicate, null, retryCount, defaultValue);
    }

    public static <T> T retry(Supplier<T> supplier, Predicate<T> predicate, Consumer<T> consumer, int retryCount) {
        return retry(supplier, predicate, consumer, retryCount, null);
    }

    public static void main(String[] args) {
        Integer result = retry(() -> new Random().nextInt(5), x -> x == 3, System.out::println, 100);
        System.out.println("得到最终结果：" + result);
    }
}
